home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / tcop / creatinh.c next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  14.2 KB  |  644 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    creatinh.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    POSTGRES create/destroy relation with inheritance utility code.
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *
  10.  *   NOTES
  11.  *
  12.  *   IDENTIFICATION
  13.  *    $Header: /private/postgres/src/tcop/RCS/creatinh.c,v 1.25 1992/08/27 04:16:35 mer Exp $
  14.  * ----------------------------------------------------------------
  15.  */
  16.  
  17. #include "tmp/postgres.h"
  18.  
  19.  RcsId("$Header: /private/postgres/src/tcop/RCS/creatinh.c,v 1.25 1992/08/27 04:16:35 mer Exp $");
  20.  
  21. /* ----------------
  22.  *    FILE INCLUDE ORDER GUIDELINES
  23.  *
  24.  *    1) tcopdebug.h
  25.  *    2) various support files ("everything else")
  26.  *    3) node files
  27.  *    4) catalog/ files
  28.  *    5) execdefs.h and execmisc.h, if necessary.
  29.  *    6) extern files come last.
  30.  * ----------------
  31.  */
  32. #include "tcop/tcopdebug.h"
  33.  
  34. #include "access/ftup.h"
  35. #include "utils/log.h"
  36. #include "parser/parse.h"
  37.  
  38. #include "nodes/pg_lisp.h"
  39. #include "nodes/primnodes.h"
  40. #include "nodes/primnodes.a.h"
  41. #include "nodes/plannodes.h"
  42. #include "nodes/plannodes.a.h"
  43. #include "nodes/execnodes.h"
  44. #include "nodes/execnodes.a.h"
  45.  
  46. #include "catalog/syscache.h"
  47. #include "catalog/catname.h"
  48. #include "catalog/pg_type.h"
  49. #include "catalog/pg_inherits.h"
  50. #include "catalog/pg_ipl.h"
  51.  
  52. #include "tcop/creatinh.h"
  53.  
  54. /* ----------------
  55.  *    external functions
  56.  * ----------------
  57.  */
  58. /*
  59.  * BuildDescForRelation --
  60.  *    Returns new tuple descriptor given schema.
  61.  */
  62. extern
  63. TupleDesc
  64. BuildDescForRelation ARGS((
  65.     List    schema,
  66.     Name    relationName
  67. ));
  68.  
  69. /* ----------------
  70.  *    local stuff
  71.  * ----------------
  72.  */
  73.  
  74. #define private
  75.  
  76. LispValue    InstalledNameValue = LispNil;
  77. LispValuePtr    InstalledNameP = &InstalledNameValue;
  78.  
  79. /*
  80.  * LispValuePInstallAsName --
  81.  *    Sets "installed name" to be value.
  82.  */
  83. private
  84. void
  85. LispValuePInstallAsName ARGS((
  86.     LispValue    *valueInP
  87. ));
  88.  
  89. /*
  90.  * CarEqualsInstalledName --
  91.  *    True iff car of list equals "installed name."
  92.  */
  93. private
  94. bool
  95. CarEqualsInstalledName ARGS((
  96.     List    list
  97. ));
  98.  
  99. /*
  100.  * MergeAttributes --
  101.  *    Returns new schema given initial schema and supers.
  102.  *
  103.  * Description:
  104.  *    The schema argument is distructively changed (unless it is LispNil,
  105.  * of course).
  106.  */
  107. private
  108. List
  109. MergeAttributes ARGS((
  110.     List    schema,
  111.     List    supers
  112. ));
  113.  
  114. /*
  115.  * StoreCatalogInheritance --
  116.  *    Updates the system catalogs with proper inheritance information.
  117.  */
  118. private
  119. void
  120. StoreCatalogInheritance ARGS((
  121.     ObjectId    objectId,
  122.     List        supers
  123. ));
  124.  
  125. /* ----------------------------------------------------------------
  126.  * CREATE relation_name '(' dom_list ')' [KEY '(' dom_name [USING operator] 
  127.  *     { , '(' dom_name [USING operator] } ')']
  128.  *     [INHERITS '(' relation_name {, relation_name} ')' ] 
  129.  *     [INDEXABLE dom_name { ',' dom_name } ] 
  130.  *     [ARCHIVE '=' (HEAVY | LIGHT | NONE)]
  131.  * 
  132.  *     `(CREATE ,relation_name
  133.  *          (
  134.  *           (KEY (,domname1 ,operator1) (,domname2 ,operator2) ...)
  135.  *           (INHERITS ,relname1 ,relname2 ...)
  136.  *           (INDEXABLE ,idomname1 ,idomname2 ...)
  137.  *           (ARCHIVE ,archive)
  138.  *          )
  139.  *          (,attname1 ,typname1) (,attname2 ,typname2) ...)
  140.  * 
  141.  *     ... where    operator?    is either ,operator or 'nil
  142.  *             archive        is one of 'HEAVY, 'LIGHT, or 'NONE
  143.  * ----------------------------------------------------------------
  144.  */
  145. /* ----------------------------------------------------------------
  146.  *    DefineRelation
  147.  *
  148.  * ----------------------------------------------------------------
  149.  */
  150. void
  151. DefineRelation(relname, parameters, schema)
  152.     char    *relname;
  153.     LispValue    parameters;
  154.     LispValue    schema;
  155. {
  156.     AttributeNumber    numberOfAttributes;
  157.     AttributeNumber    attributeNumber;
  158.     LispValue        rest         = NULL;
  159.     ObjectId        relationId;
  160.     List        arch         = NULL ;
  161.     char        archChar;
  162.     List        inheritList     = NULL;
  163.     Name        archiveName     = NULL;
  164.     Name        relationName     = NULL;
  165.     TupleDesc        descriptor;
  166.     LispValue        locargs;
  167.     int            heaploc, archloc;
  168.  
  169.     /* ----------------
  170.      *    minimal argument checking follows
  171.      * ----------------
  172.      */
  173.     AssertArg(NameIsValid(relname));
  174.     AssertArg(listp(parameters));
  175.     AssertArg(listp(schema));
  176.  
  177.     if ( strlen ( relname ) > sizeof ( NameData ))
  178.       elog(WARN, "the relation name %s is > %d characters long", relname,
  179.        sizeof(NameData));
  180.  
  181.     relationName = (Name)palloc(sizeof (NameData)+1);
  182.     bzero(relationName, sizeof (NameData)+1);
  183.     strncpy( &(relationName->data[0]), relname, sizeof (NameData) );
  184.  
  185.     /* ----------------
  186.      *     Handle parameters
  187.      *     XXX parameter handling missing below.
  188.      * ----------------
  189.      */
  190.     if (!lispNullp(CAR(parameters))) {
  191.     elog(WARN, "RelationCreate: KEY not yet supported");
  192.     }
  193.     if (!lispNullp(CADR(parameters))) {
  194.     inheritList = CDR(CADR(parameters));
  195.     }
  196.     if (!lispNullp(CADDR(parameters))) {
  197.     elog(WARN, "RelationCreate: INDEXABLE not yet supported");
  198.     }
  199.  
  200.     /* ----------------
  201.      *    determine archive mode
  202.      *     XXX use symbolic constants...
  203.      * ----------------
  204.      */
  205.     archChar = 'n';
  206.  
  207.     if (!lispNullp(arch = CADDR(CDR(parameters)))) {
  208.     switch (LISPVALUE_INTEGER(CDR(arch))) {
  209.     case NONE:
  210.         archChar = 'n';
  211.         break;
  212.  
  213.     case LIGHT:
  214.         archChar = 'l';
  215.         break;
  216.  
  217.     case HEAVY:
  218.         archChar = 'h';
  219.         break;
  220.  
  221.     default:
  222.         elog(WARN, "Botched archive mode %d, ignoring",
  223.          LISPVALUE_INTEGER(CDR(arch)));
  224.         break;
  225.     }
  226.     }
  227.  
  228.     /* figure out where to put the relation (take me to your cdr) */
  229.     locargs = CDR(CDR(CDR(CDR(parameters))));
  230.  
  231.     if (lispNullp(CAR(locargs)))
  232.     heaploc = 0;
  233.     else
  234.     heaploc = LISPVALUE_INTEGER(CDR(CAR(locargs)));
  235.  
  236.     /*
  237.      *  For now, any user-defined relation defaults to the magnetic
  238.      *  disk storgage manager.  --mao 2 july 91
  239.      */
  240.  
  241.     if (lispNullp(CADR(locargs))) {
  242.     archloc = 0;
  243.     } else {
  244.     if (archChar == 'n') {
  245.         elog(WARN, "Set archive location, but not mode, for %s",
  246.          relationName);
  247.     }
  248.     archloc = LISPVALUE_INTEGER(CDR(CADR(locargs)));
  249.     }
  250.  
  251.     /* ----------------
  252.      *    generate relation schema, including inherited attributes.
  253.      * ----------------
  254.      */
  255.     schema = MergeAttributes(schema, inheritList);
  256.  
  257.     numberOfAttributes = length(schema);
  258.     if (numberOfAttributes <= 0) {
  259.     elog(WARN, "DefineRelation: %s",
  260.          "please inherit from a relation or define an attribute");
  261.     }
  262.  
  263.     /* ----------------
  264.      *    create a relation descriptor from the relation schema
  265.      *  and create the relation.  
  266.      * ----------------
  267.      */
  268.     descriptor = BuildDescForRelation(schema, relationName);
  269.     relationId = heap_create(relationName->data,
  270.                  archChar,
  271.                  numberOfAttributes,
  272.                  heaploc,
  273.                  (struct attribute **)descriptor);
  274.  
  275.     StoreCatalogInheritance(relationId, inheritList);
  276.  
  277.     /* ----------------
  278.      *    create an archive relation if necessary
  279.      * ----------------
  280.      */
  281.     if (archChar != 'n') {
  282.     /*
  283.      *  Need to create an archive relation for this heap relation.
  284.      *  We cobble up the command by hand, and increment the command
  285.      *  counter ourselves.
  286.      */
  287.  
  288.     CommandCounterIncrement();
  289.     archiveName = (Name) palloc(sizeof(NameData));
  290.     sprintf(&archiveName->data[0], "a,%ld", relationId);
  291.     
  292.     relationId = heap_create(archiveName->data,
  293.                  'n',        /* archive isn't archived */
  294.                  numberOfAttributes,
  295.                  archloc,
  296.                  (struct attribute **)descriptor);
  297.  
  298.     pfree(archiveName);
  299.     }
  300. }
  301.  
  302. void
  303. RemoveRelation(name)
  304.     Name    name;
  305. {
  306.     AssertArg(NameIsValid(name));
  307.     
  308.     heap_destroy(name->data);
  309. }
  310.  
  311.  
  312. private
  313. void
  314. LispValuePInstallAsName(valueInP)
  315.     LispValue    *valueInP;
  316. {
  317.     InstalledNameP = valueInP;
  318. }
  319.  
  320. private
  321. bool
  322. CarEqualsInstalledName(list)
  323.     List        list;
  324. {
  325.     return (equal((Node)*InstalledNameP, (Node)CAR(list)));
  326. }
  327.  
  328. private
  329. List
  330. MergeAttributes(schema, supers)
  331.     List    schema;
  332.     List    supers;
  333. {
  334.     List    entry;
  335.     
  336.     /*
  337.      * Validates that there are no duplications.
  338.      * Validity checking of types occurs later.
  339.      */
  340.     foreach (entry, schema) {
  341.     List    rest;
  342.     
  343.     foreach (rest, CDR(entry)) {
  344.         /*
  345.          * check for duplicated relation names
  346.          */
  347.         if (equal((Node)CAR(CAR(entry)), (Node)CAR(CAR(rest)))) {
  348.         elog(WARN, "attribute \"%s\" duplicated",
  349.              CString(CAR(CAR(entry))));
  350.         }
  351.     }
  352.     }
  353.     foreach (entry, supers) {
  354.     List    rest;
  355.     
  356.     foreach (rest, CDR(entry)) {
  357.         if (equal((Node)CAR(entry), (Node)CAR(rest))) {
  358.         elog(WARN, "relation \"%s\" duplicated",
  359.              CString(CAR(CAR(entry))));
  360.         }
  361.     }
  362.     }
  363.     
  364.     /*
  365.      * merge the inherited attributes into the schema
  366.      */
  367.     foreach (entry, supers) {
  368.     LispValue    name = CAR(entry);
  369.     Relation    relation;
  370.     List        partialResult = LispNil;
  371.     AttributeNumber    attributeNumber;
  372.     TupleDesc    tupleDesc;
  373.     
  374.     AssertArg(lispStringp(name));
  375.     
  376.     /*
  377.      * grab tuple descriptor for next superclass relation
  378.      */
  379.     relation =  heap_openr(CString(name));
  380.     if (null(relation)) {
  381.         elog(WARN,
  382.          "MergeAttr: Can't inherit from non-existent superclass '%s'",
  383.          CString(name));
  384.     }
  385.     tupleDesc = RelationGetTupleDescriptor(relation);
  386.     
  387.     for (attributeNumber = RelationGetNumberOfAttributes(relation);
  388.          AttributeNumberIsValid(attributeNumber);
  389.          attributeNumber -= 1) {
  390.         
  391.         AttributeTupleForm    attribute =
  392.         tupleDesc->data[attributeNumber - 1];
  393.         
  394.         LispValue    attributeName;
  395.         LispValue    attributeType;
  396.         LispValue    match;
  397.         HeapTuple    tuple;
  398.         
  399.         /*
  400.          * form name and type
  401.          */
  402.         attributeName = lispString(&(attribute->attname.data[0]));
  403.         tuple = SearchSysCacheTuple(TYPOID,
  404.                     attribute->atttypid);
  405.         AssertState(HeapTupleIsValid(tuple));
  406.         attributeType =
  407.         lispString(&(((TypeTupleForm)GETSTRUCT(tuple))->typname.data[0]));
  408.         
  409.         /*
  410.          * check validity
  411.          *
  412.          * (find attributeName schema :test #'equal :key #'car)
  413.          */
  414.         LispValuePInstallAsName(&attributeName);
  415.         match = find_if(CarEqualsInstalledName, schema);
  416.         if (!null(match)) {
  417.         if (!equal((Node)attributeType, (Node)CADR(match))) {
  418.             elog(WARN, "%s and %s conflict for %s",
  419.              CString(attributeType),
  420.              CString(CADR(match)),
  421.              CString(attributeName));
  422.         }
  423.         /*
  424.          * this entry already exists
  425.          */
  426.         continue;
  427.         }
  428.         partialResult = nappend1(partialResult,
  429.                      cons(attributeName,
  430.                       cons(attributeType, LispNil)));
  431.     }
  432.     
  433.     /*
  434.      * iteration cleanup and result collection
  435.      */
  436.     heap_close(relation);
  437.     
  438.     schema = nconc(partialResult, schema);
  439.     }
  440.     
  441.     return (schema);
  442. }
  443.  
  444. /*
  445.  * CL copy-list
  446.  *    Returns #'equal list by copying top level of list structure.
  447.  */
  448. List
  449. lispCopyList(list)
  450.     List    list;
  451. {
  452.     List    result;
  453.     List    rest;
  454.     List    last;
  455.     
  456.     if (null(list)) {
  457.     return (LispNil);
  458.     }
  459.     AssertArg(listp(list));
  460.     
  461.     result = lispCons(CAR(list), LispNil);
  462.     
  463.     last = result;
  464.     foreach (rest, CDR(list)) {
  465.     CDR(last) = lispCons(CAR(rest), LispNil);
  466.     last = CDR(last);
  467.     }
  468.     
  469.     return (result);
  470. }
  471.  
  472. private
  473. void
  474. StoreCatalogInheritance(relationId, supers)
  475.     ObjectId    relationId;
  476.     List    supers;
  477. {
  478.     Relation    relation;
  479.     TupleDesc    desc;
  480.     int16    seqNumber;
  481.     List    entry;
  482.     List    idList;
  483.     HeapTuple    tuple;
  484.     
  485.     /* ----------------
  486.      *    sanity checks
  487.      * ----------------
  488.      */
  489.     AssertArg(ObjectIdIsValid(relationId));
  490.     
  491.     if (null(supers))
  492.     return;
  493.     
  494.     AssertArg(listp(supers));
  495.     
  496.     /* ----------------
  497.      * Catalog INHERITS information.
  498.      * ----------------
  499.      */
  500.     relation = heap_openr( InheritsRelationName );
  501.     desc = RelationGetTupleDescriptor(relation);
  502.     
  503.     seqNumber = 1;
  504.     idList = LispNil;
  505.     foreach (entry, supers) {
  506.     Datum        datum[ InheritsRelationNumberOfAttributes ];
  507.     char        nullarr[ InheritsRelationNumberOfAttributes ];
  508.     
  509.     tuple = SearchSysCacheTuple(RELNAME, CString(CAR(entry)));
  510.     AssertArg(HeapTupleIsValid(tuple));
  511.     
  512.     /*
  513.      * build idList for use below
  514.      */
  515.     idList = nappend1(idList, lispInteger(tuple->t_oid));
  516.     
  517.     datum[0] = ObjectIdGetDatum(relationId);    /* inhrel */
  518.     datum[1] = ObjectIdGetDatum(tuple->t_oid);    /* inhparent */
  519.     datum[2] = Int16GetDatum(seqNumber);        /* inhseqno */
  520.     
  521.     nullarr[0] = ' ';
  522.     nullarr[1] = ' ';
  523.     nullarr[2] = ' ';
  524.     
  525.     tuple = FormHeapTuple(InheritsRelationNumberOfAttributes, desc,
  526.                   datum, nullarr);
  527.     
  528.     (void) heap_insert(relation, tuple, NULL);
  529.     pfree(tuple);
  530.     
  531.     seqNumber += 1;
  532.     }
  533.     
  534.     heap_close(relation);
  535.  
  536.     /* ----------------
  537.      * Catalog IPL information.
  538.      *
  539.      * Algorithm:
  540.      *    0. list superclasses (by ObjectId) in order given (see idList).
  541.      *    1. append after each relationId, its superclasses, recursively.
  542.      *    3. remove all but last of duplicates.
  543.      *    4. store result.
  544.      * ----------------
  545.      */
  546.  
  547.     /* ----------------
  548.      *    1.
  549.      * ----------------
  550.      */
  551.     foreach (entry, idList) {
  552.     HeapTuple        tuple;
  553.     ObjectId        id;
  554.     int16            number;
  555.     List            next;
  556.     List            current;
  557.     InheritsTupleForm    form;
  558.     
  559.     id = CInteger(CAR(entry));
  560.     current = entry;
  561.     next = CDR(entry);
  562.     
  563.     for (number = 1; ; number += 1) {
  564.         tuple = SearchSysCacheTuple(INHRELID, id, number);
  565.         
  566.         if (! HeapTupleIsValid(tuple))
  567.         break;
  568.  
  569.         CDR(current) =
  570.         lispCons(lispInteger(((InheritsTupleForm)
  571.                       GETSTRUCT(tuple))->inhparent),
  572.              LispNil);
  573.         
  574.         current = CDR(current);
  575.     }
  576.     CDR(current) = next;
  577.     }
  578.     
  579.     /* ----------------
  580.      *    2.
  581.      * ----------------
  582.      */
  583.     foreach (entry, idList) {
  584.     LispValue    name;
  585.     List        rest;
  586.     bool        found = false;
  587.     
  588.     again:
  589.     name = CAR(entry);
  590.     foreach (rest, CDR(entry)) {
  591.         if (equal((Node)name, (Node)CAR(rest))) {
  592.         found = true;
  593.         break;
  594.         }
  595.     }
  596.     if (found) {
  597.         /*
  598.          * entry list must be of length >= 2 or else no match
  599.          *
  600.          * so, remove this entry.
  601.          */
  602.         CAR(entry) = CADR(entry);
  603.         CDR(entry) = CDR(CDR(entry));
  604.         
  605.         found = false;
  606.         goto again;
  607.     }
  608.     }
  609.     
  610.     /* ----------------
  611.      *    3.
  612.      * ----------------
  613.      */
  614.     relation = heap_openr( InheritancePrecidenceListRelationName );
  615.     desc = RelationGetTupleDescriptor(relation);
  616.     
  617.     seqNumber = 1;
  618.     
  619.     foreach (entry, idList) {
  620.     Datum    datum[ InheritancePrecidenceListRelationNumberOfAttributes ];
  621.     char    nullarr[ InheritancePrecidenceListRelationNumberOfAttributes ];
  622.     
  623.     datum[0] = ObjectIdGetDatum(relationId);    /* iplrel */
  624.     datum[1] = ObjectIdGetDatum(CInteger(CAR(entry)));
  625.     /*iplinherits*/
  626.     datum[2] = Int16GetDatum(seqNumber);        /* iplseqno */
  627.     
  628.     nullarr[0] = ' ';
  629.     nullarr[1] = ' ';
  630.     nullarr[2] = ' ';
  631.     
  632.     tuple =
  633.         FormHeapTuple( InheritancePrecidenceListRelationNumberOfAttributes,
  634.               desc, datum, nullarr);
  635.     
  636.     (void) heap_insert(relation, tuple, NULL);
  637.     pfree(tuple);
  638.     
  639.     seqNumber += 1;
  640.     }
  641.     
  642.     heap_close(relation);
  643. }
  644.